/**************************************************************************************
* FileHandler.java
* 
*************************************************************************************/
package creid.mythos.engine;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.LinkedList;

public abstract class FileHandler
{
	//Constants/////////////////////////////////////////////////////////////////////////
	//TODO: Split out common input functions: gen, sprite, id/name, properties
	
	//Data file directory
	public static final String DATA_FILE_DIR_NAME = "data";
	public static final String TITLE_PAGE_FILE = "title.txt";
	public static final String MAIN_HELP_PAGE_FILE = "help.txt";
	public static final String MAPS_GAME_FILE = "maps.game";
	public static final String TERRAIN_GAME_FILE = "terrain.game";
	public static final String ACTOR_GAME_FILE = "actors.game";
	public static final String BACKGROUND_GAME_FILE = "backgrounds.game";
	public static final String MAP_SPECIALS_GAME_FILE = "mapspecials.game";
	public static final String ITEM_GAME_FILE = "items.game";

	public static final String LINE_SPLIT = "NEWLINE";
	
	public static final int NULL_INT = -99;

	
	public static final int PLACE_MOB = 0;
	public static final int PLACE_ITEM = 1;
	public static final int PLACE_TERRAIN = 2;
	public static final int PLACE_SIZE = 3;
	
	//Attributes////////////////////////////////////////////////////////////////////////

	//Constructors//////////////////////////////////////////////////////////////////////

	//Methods///////////////////////////////////////////////////////////////////////////
	
	public static String[] loadTextFromFile(String filename, boolean dataFile)
	{
		LinkedList<String> text = new LinkedList<String>();
		BufferedReader fin = null;
		
		try
		{
			if (Mythos.RELEASE)
			{
				String path = "/" + DATA_FILE_DIR_NAME + "/" + filename;
				InputStream downStream = Mythos.class.getResourceAsStream(path);
				fin = new BufferedReader(new InputStreamReader(downStream));
			}
			else //read data files from a JAR archive
			{	
				fin = new BufferedReader(new FileReader(DATA_FILE_DIR_NAME + File.separator + filename));				
			}
		}
		catch(FileNotFoundException ex)
		{
			System.out.println("Error: could not open file " + filename + ":\n" + ex);
			return null;
		}
		
		try
		{
			while(fin.ready())
			{
				String line = fin.readLine();
				
				if (dataFile)
				{
					line = line.replaceAll("#.*$", "").trim();
					if (line.length() > 0)
						text.add(line);
				}
				else
					text.add(line);
					
			}
		} catch (IOException e)
		{
			System.out.println("Error reading input file in loadTextFromFile():");
			e.printStackTrace();
			return null;
		}
		finally //CLose our object
		{
			try
			{
				fin.close();
			} catch (IOException e)
			{
				System.out.println("Error closing input file in loadTextFromFile()");
			}
		}
		
		//Now convert list to array
		return text.toArray(new String[0]);
	}
	
	private static int getLayoutType(String type)
	{
		if (type.equals("dungeon"))
			return GameMap.LAYOUT_DUNGEON;
		
		//Default to dungeon
		Mythos.logger.errorLog("FileHandler.getLayoutType() unknown layout type '" + type + "', assuming dungeon");
		return GameMap.LAYOUT_DUNGEON;
	}
	
	/**
	 * loadMaps
	 * @return array of GameMap objects (ungenerated) with preset connections between
	 */
	public static GameMap[] loadMaps()
	{
		String[] data = loadTextFromFile(MAPS_GAME_FILE, true);
		
		LinkedList<GameMap> maps = new LinkedList<GameMap>();
		
		int mapID = NULL_INT;
		int level = NULL_INT;
		int layout = NULL_INT;
		int[] terrain = null;
		Exit[] exits = null;
		int[] mapSpecials = null;
		
		for(String line : data)
		{
			String[] content = line.split("=");
			
			//ID line starting a new map
			if (content[0].equals("Map"))
			{
				//first, save the previous object
				if (mapID != NULL_INT)
				{
					if (level == NULL_INT || layout == NULL_INT || terrain == null || exits == null)
					{
						Mythos.logger.errorLog("FileHandler.loadMaps(): malformed entry id=" + mapID);
					}
					else //Add to linked list
					{
						maps.add(new GameMap(layout, terrain, level, exits, mapSpecials));
					}
					
					//End of file
					if (content[1].equals("end")) break;
					
					//Clear old data
					layout = NULL_INT;
					terrain = null;
					level = NULL_INT;
					exits = null;
					mapSpecials = null;
				}
				
				//New map ID
				mapID = Integer.parseInt(content[1]);
			}
			else if (content[0].equals("Layout"))
			{
				layout = getLayoutType(content[1]);
			}
			else if (content[0].equals("Terrain"))
			{
				terrain = new int[]{
					Integer.parseInt(content[1]),
					Integer.parseInt(content[2]),
					Integer.parseInt(content[3]),
					Integer.parseInt(content[4]),
					Integer.parseInt(content[5]),
					Integer.parseInt(content[6])
				};
			}
			else if (content[0].equals("Encounters"))
			{
				level = Integer.parseInt(content[1]); // First entry is challenge level
			}
			else if (content[0].equals("Exits"))
			{
				exits = new Exit[content.length - 1];
				for(int i = 0; i < exits.length; i++)
				{
					String[] exitData = content[i+1].split(",");
					
					//(int terrain, int x, int y, GameMap map, int targetMap, int targetExit)
					exits[i] = new Exit(Mythos.TerrainTypes[Integer.parseInt(exitData[0])], GameMap.RANDOM_LOCATION, GameMap.RANDOM_LOCATION, null, 
							Integer.parseInt(exitData[1]), Integer.parseInt(exitData[2]));
				}
			}
			//Map specials
			else if (content[0].equals("Special"))
			{
				mapSpecials = new int[content.length - 1];
				for (int i = 0; i < mapSpecials.length; i++)
					mapSpecials[i] = Integer.parseInt(content[i+1]);
			}
			else
			{
				Mythos.logger.errorLog("Unknown content type: " + content[0] + "; ignoring line");
			}
		}
		
		return maps.toArray(new GameMap[maps.size()]);
	}
	
	/**
	 * loadTerrainTypes
	 * @return array of Cell objects containing the basic settings for different forms of terrain
	 */
	public static Cell[] loadTerrainTypes()
	{
		String[] data = loadTextFromFile(TERRAIN_GAME_FILE, true);
		
		LinkedList<Cell> terrainTypes = new LinkedList<Cell>();
		
		int terrainID = NULL_INT;
		String name = null;
		boolean passable = false;
		boolean swimmable = false;
		boolean flyable = false;
		boolean slow = false;
		boolean cover = false;
		boolean elevated = false;
		boolean opaque = false;
		boolean room = false;
		int operation = Cell.NO_OP;
		String opMsg = null;
		char[] sprite = null;
		HashMap<String, Integer> properties = new HashMap<String, Integer>();

		for(String line : data)
		{
			String[] content = line.split("=");
			
			//ID line starting a new map
			if (content[0].equals("Terrain"))
			{
				//first, save the previous object
				if (terrainID != NULL_INT)
				{
					if (name == null || sprite == null) //We don't require much for terrain, just a sprite really
					{
						Mythos.logger.errorLog("FileHandler.loadTerrainTypes(): malformed entry id=" + terrainID);
					}
					else //Add to linked list
					{
						terrainTypes.add(new Cell(name, sprite, passable, swimmable, flyable, slow, cover, elevated, opaque, room, operation, opMsg, terrainID));
					}
					
					//Add any properties described
					if (properties.keySet().size() > 0)
					{
						for (String key: properties.keySet())
						{
							terrainTypes.getLast().setProperty(key, properties.get(key));
						}
					}
					
					//Clear old data
					name = null;
					sprite = null;
					passable = false;
					swimmable = false;
					flyable = false;
					slow = false;
					cover = false;
					elevated = false;
					opaque = false;
					room = false;
					operation = Cell.NO_OP;
					opMsg = null;
					properties = new HashMap<String, Integer>();
				}
				
				//End of file
				if (content[1].equals("end")) break;
				
				//New map ID
				terrainID = Integer.parseInt(content[1]);
				name = content[2];
			}
			else if (content[0].equals("Sprite"))
			{
				sprite = new char[]{content[1].charAt(0),content[2].charAt(0)};
				if (content[1].equals("WALL"))
					sprite[0] = '#';
			}
			else if (content[0].equals("Move"))
			{
				for (int i = 1; i < content.length; i++)
				{
					if (content[i].equals("walk"))
					{
						passable = true;
					}
					else if (content[i].equals("walk"))
					{
						passable = true;
					}
					else if (content[i].equals("swim"))
					{
						swimmable = true;
					}
					else if (content[i].equals("fly"))
					{
						flyable = true;
					}
				}
			}
			else if (content[0].equals("Feature"))
			{
				for (int i = 1; i < content.length; i++)
				{
					if (content[i].equals("slow"))
					{
						slow = true;
					}
					else if (content[i].equals("cover"))
					{
						cover = true;
					}
					else if (content[i].equals("elevated"))
					{
						elevated = true;
					}
					else if (content[i].equals("opaque"))
					{
						opaque = true;
					}
					else if (content[i].equals("item"))
					{
						room = true;
					}
				}
			}
			else if (content[0].equals("Operate"))
			{
				operation = Integer.parseInt(content[1]);
				opMsg = content[2];
			}
			else
			{
				Mythos.logger.errorLog("Unknown content type: " + content[0] + "; ignoring line");
			}
		}

		//set the arrays
		return terrainTypes.toArray(new Cell[terrainTypes.size()]);
	}
	
	public static Item[] loadItems()
	{
		String[] data = loadTextFromFile(ITEM_GAME_FILE, true);
		
		LinkedList<Item> itemTypes = new LinkedList<Item>();
		
		int iid = NULL_INT;
		
		String name = null;
		String plural = null;
		
		String useVerb = null;
		
		int level = NULL_INT;
		int rarity = NULL_INT;
		int type = NULL_INT;
		char[] sprite = null;
		Item use = null;

		int element = 1;
		int power = 0;
		
		HashMap<String, Integer> properties = new HashMap<String, Integer>(); 
		
		for(String line : data)
		{
			String[] content = line.split(":");
			
			if (content[0].equals("Item"))
			{
				if (iid != NULL_INT)
				{
					if (name == null || level == NULL_INT || rarity == NULL_INT || sprite == null || type == NULL_INT)
					{
						Mythos.logger.errorLog("FileHandler.loadItems(): malformed entry id=" + iid);
					}
					else
					{
						itemTypes.add(new Item(iid, name, plural, sprite, level, rarity, type, power, element, useVerb));
						
						if (use != null)
							itemTypes.getLast().setUse(use);
						
						//Add any properties described
						if (properties.keySet().size() > 0)
						{
							for (String key: properties.keySet())
							{
								itemTypes.getLast().setProperty(key, properties.get(key));
							}
						}
					}
					
					//End of file
					if (content[1].equals("end")) break;
					
					name = null;
					plural = null;
					useVerb = null;
					level = NULL_INT;
					rarity = NULL_INT;
					type = NULL_INT;
					sprite = null;
					element = 1;
					power = 0;
					properties = new HashMap<String, Integer>();
					use = null;
				}
				
				iid = Integer.parseInt(content[1]);
				name = content[2];
				plural = content[3];
			}
			else if (content[0].equals("Sprite"))
			{
				sprite = new char[]{content[1].charAt(0),content[2].charAt(0)};
				if (content[1].equals("WALL"))
					sprite[0] = '#';
				else if (content[1].equals("COLON"))
					sprite[0] = ':';
			}
			else if (content[0].equals("Use"))
			{
				//(int id, String singular, String plural, char[] sprite, int level, int rarity, int type, int power, int element, String useVerb)
				
				int projectionType = Integer.parseInt(content[2]);
				
				int range = Projection.STANDARD_RANGE;
				if (content.length >= 8)
					range = Integer.parseInt(content[7]);
				
				int radius = 0;
				if (content.length == 9)
					radius = Integer.parseInt(content[8]);

				use = new Item(-1, "effect", null, new char[]{content[5].charAt(0), content[6].charAt(0)}, -1, Entity.NEVER_GEN, Item.I_EFFECT, 
						Integer.parseInt(content[3]), Integer.parseInt(content[4]), content[1]);
				
				
				use.setProperty("radius", radius);
				use.setProperty("range", range);
				use.setProperty("projectionType", projectionType);
			}
			else if (content[0].equals("Spawn"))
			{
				type = Integer.parseInt(content[1]);
				level = Integer.parseInt(content[2]);
				rarity = Integer.parseInt(content[3]);
			}
			else if (content[0].equals("Combat"))
			{
				power = Integer.parseInt(content[1]);
				element = Integer.parseInt(content[2]);
			}
			else if (content[0].equals("Properties"))
			{
				for (int i = 1; i < content.length; i++)
				{
					String[] entry = content[i].split("=");
					int value = 1;
					if (entry.length == 2)
						value = Integer.parseInt(entry[1]);
					
					properties.put(entry[0], value);
				}
			}
		}

		return itemTypes.toArray(new Item[itemTypes.size()]);
	}
	
	private static int getAttackElement(String name)
	{
		return Entity.PHYSICAL;
	}
	
	public static Actor[] loadActors()
	{
		String[] data = loadTextFromFile(ACTOR_GAME_FILE, true);
		
		LinkedList<Actor> actorTypes = new LinkedList<Actor>();
		
		int aid = NULL_INT;
		String name = null;
		String plural = null;
		char[] sprite= null;
		int level = NULL_INT;
		int rarity = NULL_INT;
		int faction = NULL_INT;
		int pathType = NULL_INT;
		int preferredRange = NULL_INT;
		int vigilance = NULL_INT;
		int speed = NULL_INT;
		boolean walk = false;
		boolean swim = false;
		boolean fly = false;
		int size = NULL_INT;
		int brawn = NULL_INT;
		int grace = NULL_INT;
		int will = NULL_INT;
		Item attack = null;
		Item attack2 = null;
		int defense = 0;
		StringBuilder descriptionInOneLine = null;
		HashMap<String, Integer> properties = new HashMap<String, Integer>(); 
		
		for(String line : data)
		{
			String[] content = line.split(":");
			
			if (content[0].equals("Actor"))
			{
				//Save the previous creature
				if (aid != NULL_INT)
				{
					if (name == null || sprite == null || level == NULL_INT || faction == NULL_INT || pathType == NULL_INT || preferredRange == NULL_INT ||
							vigilance == NULL_INT || size == NULL_INT || brawn == NULL_INT || rarity == NULL_INT || grace == NULL_INT || will == NULL_INT)
					{
						Mythos.logger.errorLog("FileHandler.loadActors(): malformed entry id=" + aid);
					}
					else
					{
						actorTypes.add(new Actor(aid, name, plural, sprite, level, size, rarity,
								//AI stuff
								faction, pathType, preferredRange, vigilance,
								//Mobility
								walk, swim, fly, speed,
								//Combat stats
								defense, brawn, grace, will, attack, attack2));
						
						//Add any properties described
						if (properties.keySet().size() > 0)
						{
							for (String key: properties.keySet())
							{
								actorTypes.getLast().setProperty(key, properties.get(key));
							}
						}
						
						if (descriptionInOneLine != null)
							actorTypes.getLast().setDetails(descriptionInOneLine.toString().split(LINE_SPLIT));
					}
					
					//Clear previous entry's data
					aid = NULL_INT;
					name = null;
					plural = null;
					sprite= null;
					level = NULL_INT;
					faction = NULL_INT;	
					pathType = NULL_INT;
					preferredRange = NULL_INT;
					vigilance = NULL_INT;
					speed = NULL_INT;
					walk = false;
					swim = false;
					fly = false;
					defense = 0;
					size = NULL_INT;
					brawn = NULL_INT;
					grace = NULL_INT;
					attack = null;
					attack2 = null;
					descriptionInOneLine = null;
					will = NULL_INT;
					properties = new HashMap<String, Integer>();
				}
				
				//End of file
				if (content[1].equals("end")) break;
				
				//Add new info
				aid = Integer.parseInt(content[1]);
				name = content[2];
				plural = content[3];
			}
			else if (content[0].equals("Sprite"))
			{
				sprite = new char[]{content[1].charAt(0),content[2].charAt(0)};
				if (content[1].equals("WALL"))
					sprite[0] = '#';
				else if (content[1].equals("COLON"))
					sprite[0] = ':';
			}
			else if (content[0].equals("Gen"))
			{
				faction = Integer.parseInt(content[1]);
				level = Integer.parseInt(content[2]);
				rarity = Integer.parseInt(content[3]);
			}
			else if (content[0].equals("AI"))
			{
				pathType = Integer.parseInt(content[1]);
				preferredRange = Integer.parseInt(content[2]);
				vigilance = Integer.parseInt(content[3]);
			}
			else if (content[0].equals("Move"))
			{
				speed = Integer.parseInt(content[1]);
				
				for (int i = 2; i < content.length; i++)
				{
					if (content[i].equals("walk"))
						walk = true;
					else if (content[i].equals("swim"))
						swim = true;
					else if (content[i].equals("fly"))
						fly = true;
				}
			}
			else if (content[0].equals("Stats"))
			{
				brawn = Integer.parseInt(content[2]);
				grace = Integer.parseInt(content[3]);
				will = Integer.parseInt(content[4]);
				
				size = Actor.MEDIUM;
				if (content[1].equals("small"))
					size = Actor.SMALL;
				else if (content[1].equals("large"))
					size = Actor.LARGE;
			}
			else if (content[0].equals("Attack"))
			{
				Item att = new Item(-1, "Attack", null, null, 0, Entity.NEVER_GEN, Item.I_NATURAL_ATTACK, Integer.parseInt(content[3]), getAttackElement(content[2]), content[1]);
				if (attack == null)
					attack = att;
				else
					attack2 = att;
			}
			else if (content[0].equals("Properties"))
			{
				for (int i = 1; i < content.length; i++)
				{
					String[] entry = content[i].split("=");
					properties.put(entry[0], Integer.parseInt(entry[1]));
				}
			}
			else if (content[0].equals("Text"))
			{
				if (descriptionInOneLine == null)
					descriptionInOneLine = new StringBuilder(content[1]);
				else //appending
					descriptionInOneLine.append(LINE_SPLIT + content[1]);
			}
		}
		
		return actorTypes.toArray(new Actor[actorTypes.size()]);
	}
	
	/**
	 * loadBackgrounds
	 * @return backgrounds
	 */
	public static Actor[] loadBackgrounds()
	{
		String[] data = loadTextFromFile(BACKGROUND_GAME_FILE, true);
		
		LinkedList<Actor> backgrounds = new LinkedList<Actor>();
		
		int aid = NULL_INT;
		String name = null;
		String plural = null;
		char[] sprite= null;
		int speed = NULL_INT;
		boolean walk = false;
		boolean swim = false;
		boolean fly = false;
		int size = NULL_INT;
		int brawn = NULL_INT;
		int grace = NULL_INT;
		int will = NULL_INT;
		
		/*#Background
		#Sprite:symbol:color
		#Move:speed:walk:swim:fly
		#Stats:size:brawn:grace:will
		#Defense:armor[:element=X]
		#Properties:
		#Text:*/

		StringBuilder descriptionInOneLine = null;
		HashMap<String, Integer> properties = new HashMap<String, Integer>(); 
		
		for(String line : data)
		{
			String[] content = line.split(":");
			
			if (content[0].equals("Background"))
			{
				//Save the previous creature
				if (aid != NULL_INT)
				{
					if (name == null || sprite == null || size == NULL_INT || brawn == NULL_INT || grace == NULL_INT || will == NULL_INT)
					{
						Mythos.logger.errorLog("FileHandler.loadBackgrounds(): malformed entry id=" + aid);
					}
					else
					{
						if (speed == NULL_INT)
							speed = 0;
						
						backgrounds.add(new Actor(aid, name, plural, sprite, 1, size, Entity.NEVER_GEN,
								//AI stuff
								Actor.PLAYER_FACTION, GameMap.ALLY_PATH, 0, 0,
								//Mobility
								walk, swim, fly, speed,
								//Combat stats
								0, brawn, grace, will, new Item(-1, "unarmed attack", null, null, 0, 0, Item.I_NATURAL_ATTACK, 0, 0,"punches"), null));
						
						//Add any properties described
						backgrounds.getLast().setProperty("Elite", 1);
						if (properties.keySet().size() > 0)
						{
							for (String key: properties.keySet())
							{
								backgrounds.getLast().setProperty(key, properties.get(key));
							}
						}
						
						if (descriptionInOneLine != null)
							backgrounds.getLast().setDetails(descriptionInOneLine.toString().split(LINE_SPLIT));
					}
					
					//End of file
					if (content[1].equals("end")) break;
					
					//Clear previous entry's data
					aid = NULL_INT;
					name = null;
					plural = null;
					sprite= null;
					speed = NULL_INT;
					walk = false;
					swim = false;
					fly = false;
					size = NULL_INT;
					brawn = NULL_INT;
					grace = NULL_INT;
					descriptionInOneLine = null;
					will = NULL_INT;
					properties = new HashMap<String, Integer>();
				}
				
				//Add new info
				aid = Integer.parseInt(content[1]);
				name = content[2];
			}
			else if (content[0].equals("Sprite"))
			{
				sprite = new char[]{content[1].charAt(0),content[2].charAt(0)};
				if (content[1].equals("WALL"))
					sprite[0] = '#';
			}
			else if (content[0].equals("Move"))
			{
				speed = Integer.parseInt(content[1]);
				
				for (int i = 2; i < content.length; i++)
				{
					if (content[i].equals("walk"))
						walk = true;
					else if (content[i].equals("swim"))
						swim = true;
					else if (content[i].equals("fly"))
						fly = true;
				}
			}
			else if (content[0].equals("Stats"))
			{
				brawn = Integer.parseInt(content[2]);
				grace = Integer.parseInt(content[3]);
				will = Integer.parseInt(content[4]);
				
				size = Actor.MEDIUM;
				if (content[1].equals("small"))
					size = Actor.SMALL;
				else if (content[1].equals("large"))
					size = Actor.LARGE;
			}
			else if (content[0].equals("Properties"))
			{
				for (int i = 1; i < content.length; i++)
				{
					String[] entry = content[i].split("=");
					properties.put(entry[0], Integer.parseInt(entry[1]));
				}
			}
			else if (content[0].equals("Text"))
			{
				if (descriptionInOneLine == null)
					descriptionInOneLine = new StringBuilder(content[1]);
				else //appending
					descriptionInOneLine.append(LINE_SPLIT + content[1]);
				
				if (content.length > 2)
					for (int i = 2; i < content.length; i++)
						descriptionInOneLine.append(content[i]);
			}
		}
		
		//Common Properties all backgrounds should have
		for(Actor bg: backgrounds)
		{
			//Open/close doors
			bg.setProperty("operate", 1);
		}
		
		return backgrounds.toArray(new Actor[backgrounds.size()]);
	}
	
	static MapSpecial[] loadSpecialRooms()
	{
		LinkedList<MapSpecial> rooms = new LinkedList<MapSpecial>();
		String[] data = loadTextFromFile(MAP_SPECIALS_GAME_FILE, true);

		int roomID = NULL_INT;
		int level = NULL_INT;
		char[][] roomMap = null;
		String[] specials = null; //Placing creatures, items, etc
		int width = NULL_INT;;
		int height = NULL_INT;
		int rarity = NULL_INT;
		int row = 0;
		
		for(String line: data)
		{
			String[] content = line.split("=");
			
			if (content[0].equals("MapSpecial"))
			{
				if (roomID != NULL_INT)
				{
					if (roomMap == null || level == NULL_INT || rarity == NULL_INT)
						Mythos.logger.errorLog("FileHandler.loadSpecialRooms(): malformed entry id=" + roomID);
					else
					{
						rooms.add(new MapSpecial(roomMap, specials, rarity));
					}
				}
				
				//End of file
				if (content[1].equals("end")) break;

				//Clear old data
				roomMap = null;
				specials = null;
				width = NULL_INT;
				height = NULL_INT;
				rarity = NULL_INT;
				level = NULL_INT;
				row = 0;
				
				roomID = Integer.parseInt(content[1]);
				width = Integer.parseInt(content[2]);
				height = Integer.parseInt(content[3]);
				
				roomMap = new char[width][height];
				
				for (int x = 0; x < width; x++)
					for (int y = 0; y < height; y++)
						roomMap[x][y] = '|';
			}
			else if (content[0].equals("Gen"))
			{
				level = Integer.parseInt(content[1]);
				rarity = Integer.parseInt(content[2]);
			}
			else if (content[0].equals("R"))
			{
				if (row == roomMap.length)
				{
					Mythos.logger.errorLog("Ignoring invalid R line for roomID " + roomID + " (" + line + ")");
					continue;
				}
				
				for (int col = 0; col < roomMap[0].length; col++)
				{
					roomMap[row][col] = content[1].charAt(col);
				}
				
				row++;
			}
			else if (content[0].equals("Symbols"))
			{
				specials = new String[content.length - 1];
				for(int i = 1; i < content.length; i++)
				{
					specials[i-1] = content[i];
				}
			}
		}
		
		return rooms.toArray(new MapSpecial[rooms.size()]);
	}
}
